home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-01-11 | 8.8 KB | 207 lines | [TEXT/CWIE] |
- /*———————————————————————————————————————————————————————————————————————————————————————————————————
- DATA PERSISTENCE README
- ———————————————————————
- • WHAZZAT
-
- Very general mini-module for saving and restoring arbitrary blocks of data, in
- resource format in a separate file. It's very small (1K including data), very
- simple (four main routines), and does the job, at least for me.
-
- This code was initially part of SpritePersistence. On second thought,it's better
- and more useful as a separate module, so it was made into one.
-
-
- • USAGE
-
- This is it:
-
- err = SWGOpenPersistenceFile (); // note: no args
- // should ALWAYS check error!..
- err = SWGSaveRecord (yourDataPtr, yourDataSize, resID); // or SWGLoadRecord
- // should ALWAYS check error!..
- SWGClosePersistenceFile ();
-
- That's all folks. It looks simple enough to me not to need a lot of comment...
-
-
- • FUNCTION REFERENCE
-
- 1. File
-
- OSErr SWGOpenPersistenceFile (void);
-
- No arguments: the file name is a customizable global pascal string
- named gPersistenceFileName (see DataPersistence.h; change it if you like).
- System errors may be returned. But fnfErr (file not found) will never
- be returned: if file is absent, we will switch to application resource mode
- (see the File Management section).
-
- void SWGClosePersistenceFile (void);
-
- Guess.
-
- Boolean SWGOpenPersistenceFileConditionally (OSType newType);
-
- newType: optionally overrides DataPersistence's standard resource
- type. If you pass kNoNewType, there will be no override.
- You normally don't need this, it's mainly for SpritePersistence which
- uses the override mechanism to avoid overwriting your own resources.
-
- This is primarily for the benefit or SpritePersistence. (Have a look at
- SpritePersistence if you want to see the reason.)
-
- - It returns true if the file was previously closed, and it has just opened the
- file; after that, your routine is responsible for closing the file, using
- SWGClosePersistenceFile() before returning.
-
- - If it returns false, the file was already open, and it must stay open when
- your routine terminates. So your routine must _not_ close the file.
-
- For an example of usage, see the SpritePersistence module,
- SWGSaveSpritesInAllLayers and SWGSaveSpritesInLayer.
-
- There are twe reasons you may want to use this instead of SWGOpenPersistenceFile.
- One is if you really need to override the default resource type ('PERS').
- The second is the same reason SpritePersistence uses it: when there are
- several nested routines, it allows calling directly one of the lower-level
- nested ones. It resolves the problem "should I open the file/should I close it?".
- (Again, look at SpritePersistence if you want a detailed look at this issue.)
-
- 2. Read/Write
-
- OSErr SWGSaveRecord (Ptr recordP, Size recSize, SInt16 resourceID);
- OSErr SWGLoadRecord (Ptr recordP, Size recSize, SInt16 resourceID);
-
- For both:
-
- recordP: pointer to your data (if dereferenced handle, *lock* it)
- recSize: *exact* number of bytes to read/write
- resourceID: whatever you like (apple-recommended range 128..32767,
- but actually we may use -32768..32767 as there should be
- no conflict between gSWGPersistenceResourceType (which is
- 'PERS' by default) and apple resources.
-
- OSErr SWGSaveString (Ptr stringP, Size stringSize, SInt16 resourceID);
-
- This is strictly indentical to SWGSaveRecord; it's here for symmetry
- with SWGLoadString.
-
- The following is nearly identical with SWGLoadRecord, but with a little twist
- which regards error reporting:
-
- OSErr SWGLoadString (Ptr stringP, Size maxStringSize, SInt16 resourceID);
-
- stringP: pointer to your data (if dereferenced handle, *lock* it)
- maxStringSize: *max* number of bytes to read/write
- resourceID: same as above
-
- The only difference between SWGLoadRecord and SWGLoadString is tolerance to
- an unexpected file data size:
-
- - SWGLoadRecord expects an exact size and will report an error if another size
- is found (you are free to ignore the error if you feel it's appropriate). It
- may report system errors, plus the two specials: kDataSizeBiggerError and
- kDataSizeSmallerError.
-
- - SWGLoadString considers data smaller than expected as normal, and only
- reports an error if the data is *bigger* than expected. It may report system
- errors, plus one special: kDataSizeBiggerError.
-
- 3. Errors
-
- void SWGErrorReportingStub (OSErr err);
-
- If there's an error, will beep. Change this behavior to whatever
- sophisticated behavior each app needs.
- If there's no error, does nothing; which allows you to call it
- systematically, if you prefer having a slightly more compact source
- code at the expense of a few clock cycles at runtime.
-
-
- • NOTES
-
- 1. ** IMPORTANT AND USEFUL ** : you may change data block sizes at any time.
- DataPersistence automatically resizes the resource when asked to write a data block
- with a modified size.
-
- 2. Error checking is recommended (yes, I know you know :)
- If you don't really want to go to a lot of trouble, there's a simple error routine
- in DataPersistence, called SWGErrorReportingStub. You could do this:
-
- err = SWGOpenPersistenceFile ();
- SWGErrorReportingStub (err); // beeps only if err
- err = SWGSaveRecord (yourDataPtr, yourDataSize, resID);
- SWGErrorReportingStub (err); // beeps only if err
- SWGClosePersistenceFile ();
-
- 3. When writing, DataPersistence automatically creates a resource when it didn't
- already exist.
-
- 4. When reading, if a resource doesn't exist, DataPersistence zeroes the recordP and
- returns with resNotFound. This will usually happen only after the first launch.
-
- 5. ** Warning ** : if yourDataPtr is a dereferenced handle, *lock* the handle before
- calling; you can of course unlock it just after the call. Never ever call with an
- unlocked dereferenced handle, it always brings bad luck (and sometimes bad crashes :)
-
- 6. If you need to manually edit some of your saved data: look in the saved file (or
- the app's resource fork if that's what you use), for the resource type 'PERS'. This
- default type is defined by kDefaultPersistenceRezType in file DataPersistence.h
- (change it if you wish). If you want to edit sprite data: SpritePersistence overrides
- the standard resource type and uses type 'SPRI', defined by kSpriteSaveRezType in
- SpritePersistence.h (change it if you wish).
-
-
- • FILE MANAGEMENT
-
- DataPersistence normally uses a separate resource file, named "Data Persistence" by
- default, which resides in the app's folder. This is the recommended usage: the app's
- own resources will be clobbered the very next time you rebuild it.
-
- The default data file name may be changed: gPersistenceFileName in DataPersistence.h .
-
- There's an alternative mode which uses the app's resource fork.
-
- If the "Data Persistence" file is not found, we automatically switch to the other mode,
- which uses the application resource fork. To go back to the recommended separate-file
- mode, simply quit your app, bring back the "Data Persistence" file in the app's folder,
- and relaunch.
-
- Note: you are free to give any file type and creator to the "Data Persistence" file.
- DataPersistence identifies the file from it's name and it's location in the app's
- folder, not from the type and creator.
-
- Note 1: the alternative mode using app resources has a side-effect: the data file is
- _not_ created implicitly, when it is not found. If you want it you must create it
- yourself.
-
- Note 2: this is a *resource* file. This means you must have created it with resedit
- or resorcerer (for example), definitely not with your favorite text editor.
-
- Note on resource format
- -----------------------
- The data is saved in resource format; you may inspect it or edit it manually with
- resedit/resorcerer. This format is not intended for a large number of stored elements
- (e.g. in the thousands). But resources are very convenient, and there are many
- toolbox calls and many utility programs for manipulating them. Even if we need
- several thousand elements, it will work perfectly, although a little more slowly.
- In most cases, this won't be a drawback, since most read/writes will be
- done when the animation isn't running.
-
- If necessary in the future, it would be reasonably easy to modify SWGSaveRecord and
- SWGLoadRecord, using a custom data format. It looks like unneeded work at then moment,
- and it would make this module significantly larger (think of the automatic record
- resizing facility). If you become unhappy with using resources, why not say so... we'll
- talk about it.
-
-
- • FAQ
-
- ----- 1 -----
-
- Q: I have no questions at this time, bud.
- A: Why?
-
- ———————————————————————————————————————————————————————————————————————————————————————————————————*/
- // feedback: macdev@tnuctip.com
-